#ifndef UI_H
#define UI_H

#include <QtGui>
#include <QVTKWidget.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/point_picking_event.h>
#include <pcl/visualization/interactor.h>
#include <vtkSmartPointer.h>
#include "pcqc.h"

/**
 * @brief Class implementing the application user interface.
 * @author Alberto Basso, Luca Tumelero
 * @file ui.h
 *
 */
class Ui : public QMainWindow
{
    Q_OBJECT

public:

    // INIT
/**
 * @brief Constructor
 *
 * @param[in] pcqc Pointer to the motor object.
 */
    Ui(Pcqc *pcqc);
    /**
     * @brief
     *
     */
    ~Ui();

    // SETTERS
    /**
     * @brief Set another motor for the UI to work with different Pcqc instances.
     *
     * @param[in] pcqc
     */
    void setMotor(Pcqc *pcqc);

    // GETTERS
    /**
     * @brief Get a pointer to the motor object.
     *
     * @return Pcqc Pointer to the motor object.
     */
    Pcqc* getMotor();
    /**
     * @brief Get a pointer to the add component dialog viewer.
     *
     * @return pcl::visualization::PCLVisualizer Pointer to the add component dialog viewer.
     */
    pcl::visualization::PCLVisualizer* getDialogViewer();
    /**
     * @brief Get a pointer to the add compoennt dialog widget.
     *
     * @return QDialog Pointer to the add compoennt dialog widget.
     */
    QDialog* getComponentDialog();

public slots:
    /**
     * @brief Show the reference cloud in the main viewer
     *
     */
    void showTarget();
    /**
     * @brief Show the registered sample cloud in the main viewer
     *
     */
    void showRegistered();
    /**
     * @brief Show the registered sample cloud in the main viewer for Ardoran PCB.
     *
     */
    void showArdoranRegistered();

private slots:
    /**
     * @brief About menu entry.
     *
     */
    void about();
    /**
     * @brief About Point Cloud Library menu entry.
     *
     */
    void aboutPCL();
    /**
     * @brief Open file browser window to load the reference cloud.
     *
     */
    void browseLoadTarget();
    /**
     * @brief Open file browser window to load the sample cloud.
     *
     */
    void browseLoadSource();
    /**
     * @brief Open a dialog window to select the components to check.
     *
     */
    void openComponentDialog();
    /**
     * @brief Resets the point pick callback to the dialog point cloud viewer.
     *
     */
    void resetComponentDialogCallback();
    /**
     * @brief Set the color threshold for the component selection.
     *
     */
    void setColorThreshold();
    /**
     * @brief Set the clustering threshold for the component selection.
     *
     */
    void setClusterThreshold();
    /**
     * @brief Set the clustering threshold for the automatic component selection.
     *
     */
    void setClusterAutoThreshold();
    /**
     * @brief Set the score distance threshold described in registration.h
     *
     */
    void setScoreDistanceThreshold();
    /**
     * @brief Remove all the cloud but the selected component from the dialog viewer.
     *
     */
    void segmentComponent();
    /**
     * @brief Save the last selected component.
     *
     */
    void saveComponent();
    /**
     * @brief Delete the component selected in the components list, also remove any associated check and component from the visualizer.
     *
     */
    void deleteComponent();
    /**
     * @brief Find the cloud components automatically and show them in the dialog viewer.
     *
     */
    void autoFindComponent();
    /**
     * @brief Add the last automatically foud components to the component list.
     *
     */
    void autoAddComponent();
    /**
     * @brief Open a dialog window to select the checks to perform.
     *
     */
    void openCheckDialog();
    /**
     * @brief Save the defined check.
     *
     */
    void saveCheck();
    /**
     * @brief Delete the check selected in the check list
     *
     */
    void deleteCheck();
    /**
     * @brief Perform the defined checks on the selected components.
     *
     */
    void check();
    /**
     * @brief Show the difference sample cloud in the main viewer.
     *
     */
    void showDifference();
    /**
     * @brief Show the target component selected in the combo box in the main viewer.
     * @deprecated No longer used.
     *
     */
    void showTargetComponent();
    /**
     * @brief Show the source component selected in the combo box in the main viewer.
     * @deprecated No longer used.
     *
     */
    void showSourceComponent();
    /**
     * @brief Show the target/source component selected in the combo box in the main viewer.
     *
     */
    void showComponent();
    /**
     * @brief Hide all component in the main viewer
     *
     */
    void clearAll();

    /**
     * @brief Open file browser window to load the reference cloud for the Ardoran PCB.
     * @deprecated No longer used.
     *
     */
    void browseLoadTargetArdoran();
    /**
     * @brief Open file browser window to load the sample cloud for the Ardoran PCB.
     *
     */
    void browseLoadSourceArdoran();
    /**
     * @brief Open file browser window to load all the cloud in a directory as sample cloud for the Ardoran PCB.
     *
     */
    void browseLoadMultiSourceArdoran();
    /**
     * @brief Perform ribbon cable connection checks for the Ardoran PCB.
     *
     */
    void checkArdoran();


private:
// UI FUNCTIONS
    /**
     * @brief Set up the interface menu bar.
     *
     */
    void setupMenuBar();
    /**
     * @brief Set up the interface status bar.
     *
     */
    void setupStatusBar();
    /**
     * @brief Set up the interface load reference cloud box.
     *
     */
    void setupLoadTBox();
    /**
     * @brief Set up the interface load sample cloud box.
     *
     */
    void setupLoadSBox();
    /**
     * @brief Set up the interface component list and add/delete button.
     *
     */
    void setupComponentsBox();
    /**
     * @brief Set up the interface check list and add/delete button.
     *
     */
    void setupChecksBox();
    /**
     * @brief Set up the interface main visualizer.
     *
     */
    void setupVisualizer();
    /**
     * @brief Set up the interface result box.
     *
     */
    void setupResultsBox();
    /**
     * @brief Set up the interface check button and sensibility slider box.
     *
     */
    void setuCheckCommandBox();
    /**
     * @brief Set up the interface visualizer commands box.
     *
     */
    void setupVisualizerCommandsBox();
    /**
     * @brief Set up the interface mail layout.
     *
     */
    void setupMainLayout();
    /**
     * @brief Point pick callback function to collect user's clicks on the visualizer.
     *
     * @param event The click on a point event.
     * @param cookie A pointer to the Ui object to interact with it at every click.
     */
    static void pointPickCallback(const pcl::visualization::PointPickingEvent& event, void* cookie);
    /**
     * @brief Point pick callback function to collect user's clicks on the component's definition visualizer.
     *
     * @param[in] event The click on a point event.
     * @param[in] cookie A pointer to the Ui object to interact with it at every click.
     */
    static void pointPickCallbackSelectComponent(const pcl::visualization::PointPickingEvent& event, void* cookie);
    /**
     * @brief Converts a QColor to a style sheet.
     *
     * @param[in] color The input color to transform.
     * @return QString The string representing the style sheet.
     */
    static QString colorToStyleSheet(QColor *color);
    /**
     * @brief Set up the interface source component combobox.
     *
     */
    void setupSourceComboBox();
    /**
     * @brief Set up the interface checks combobox inserting all the selected components.
     *
     * @param cb Pointer to the combobox to set up.
     */
    void setupChecksComboBox(QComboBox *cb);
    /**
     * @brief Set up the interface load sample cloud box for the Ardoran PCB.
     *
     */
    void setupLoadSBoxArdoran();
    /**
     * @brief Set up the interface load multiple sample cloud box for the Ardoran PCB.
     *
     */
    void setupMultiLoadSBoxArdoran();

    /**
     * @brief Set up the interface visualizer for the Ardoran tab.
     *
     */
    void setupVisualizerArdoran();
    /**
     * @brief Set up the interface results box for the Ardoran tab.
     *
     */
    void setupResultsBoxArdoran();


// Motor object
    Pcqc *motor; /**< The Pcqc motor object containig the logic of the application. */

// Main UI
    QLineEdit *pathTField; /**< Editable line containing the path to the reference cloud. */
    QLineEdit *pathSField; /**< Editable line containing the path to the sample cloud. */
    QDir launchDirectory; /**< Directory object containig the path from where the application is launched. */
    QListWidget *componentsList; /**< List containing the selected components. */
    QListWidget *checksList; /**< List containing the checks to perform. */

    QTextEdit *resultsList; /**< Text field for the results output. */
    QComboBox *targetComponentsList; /**< Combobx containing the selected components. */
    QComboBox *sourceComponentsList; /**< Combobx containing the matched components. */
    QVTKWidget *qvtkVisualizer; /**< Widget containing the PCL viewer for the main window. */
    QVTKWidget *dialogVisualizer; /**< Widget containing the PCL viewer for the add component dialog window tab. */
    QVTKWidget *dialogVisualizerAuto; /**< Widget containing the PCL viewer for the automatic add component dialog window tab. */
    pcl::visualization::PCLVisualizer *viewer; /**< The PCL visualizer. */
    QWidget* loadTBox; /**< The interface box containing the load reference cloud button an the editable line containing the path to the reference cloud.*/
    QGroupBox *componentsBox; /**< Combobox containing all the selected components. */
    QGroupBox *checksBox; /**< Combobox containing all the checks to perform. */
    QWidget *loadSBox; /**< The interface box containing the load sample cloud button an the editable line containing the path to the sample cloud.*/
    QGroupBox *resultsBox; /**< The inteface box containing the result list. */
    QGroupBox *checkCommandBox; /**< The interface box containing the check button and sensibility slider box. */
    QGroupBox *visualizerCommandsBox; /**< The interface box containing the visualizer commands box. */

//Ardoran UI
    QVTKWidget *qvtkVisualizerArdoran; /**< Widget containing the PCL viewer for the Ardoran tab. */
    pcl::visualization::PCLVisualizer *viewerArdoran; /**< The PCL visualizer for the Ardoran tab. */
    QWidget *loadSBoxArdoran; /**< The interface box containing the load sample cloud button an the editable line containing the path to the sample cloud for the Ardoran PCB.*/
    QGroupBox *resultsBoxArdoran; /**< The inteface box containing the result list for the Ardoran tab. */
    QLineEdit *pathTFieldArdoran; /**< Editable line containing the path to the reference cloud for the Ardoran PCB. */
    QLineEdit *pathSFieldArdoran; /**< Editable line containing the path to the sample cloud for the Ardoran PCB. */
    QStringList *files; /*!< List of strings containing the name of the source clouds files for the Ardoran PCB. */
    QWidget *loadMBoxArdoran; /**< The interface box containing the load multiple sample cloud button an the editable line containing the path to the sample clouds for the Ardoran PCB.*/
    QLineEdit *pathMFieldArdoran; /**< Editable line containing the path to the sample clouds for the Ardoran PCB. */
    QTextEdit *resultsListArdoran; /**< Text field for the results output for the Ardoran tab. */

// Dialog UIs
    QDialog *addComponentDialog; /**< The add component dialog window. */
    boost::signals2::connection componentCallbackConnection;/**< Callback connection to the add component dialog window. */
    pcl::visualization::PCLVisualizer *dialogViewer; /**< The PCL visualizer for the add component dialog window tab. */
    pcl::visualization::PCLVisualizer *dialogViewerAuto;  /**< The PCL visualizer for the automatic add component dialog window tab. */
    QDialog *addCheckDialog; /**< The add check dialog window. */
    int componentsFound;  /**< The number of components found by the auto find component method. */
};

#endif // UI_H
